"""公共组件模块的数据模型

定义系统通用的数据模型，包括系统配置、通知、日志等。
"""

import uuid
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey
from django.core.validators import MinLengthValidator

User = get_user_model()


class SystemConfig(models.Model):
    """系统配置模型
    
    存储系统级别的配置信息。
    """
    
    # 配置类型选择
    CONFIG_TYPES = [
        ('string', _('字符串')),
        ('integer', _('整数')),
        ('float', _('浮点数')),
        ('boolean', _('布尔值')),
        ('json', _('JSON对象')),
        ('text', _('长文本')),
    ]
    
    key = models.CharField(
        _('配置键'),
        max_length=100,
        unique=True,
        help_text=_('配置项的唯一标识')
    )
    
    value = models.TextField(
        _('配置值'),
        help_text=_('配置项的值')
    )
    
    value_type = models.CharField(
        _('值类型'),
        max_length=20,
        choices=CONFIG_TYPES,
        default='string',
        help_text=_('配置值的数据类型')
    )
    
    description = models.TextField(
        _('描述'),
        blank=True,
        help_text=_('配置项的描述信息')
    )
    
    # 分组
    group = models.CharField(
        _('配置分组'),
        max_length=50,
        default='general',
        help_text=_('配置项所属的分组')
    )
    
    # 是否可编辑
    is_editable = models.BooleanField(
        _('可编辑'),
        default=True,
        help_text=_('配置项是否可以通过界面编辑')
    )
    
    # 是否敏感信息
    is_sensitive = models.BooleanField(
        _('敏感信息'),
        default=False,
        help_text=_('是否为敏感配置信息')
    )
    
    # 时间字段
    created_at = models.DateTimeField(
        _('创建时间'),
        auto_now_add=True
    )
    
    updated_at = models.DateTimeField(
        _('更新时间'),
        auto_now=True
    )
    
    class Meta:
        verbose_name = _('系统配置')
        verbose_name_plural = _('系统配置')
        db_table = 'system_config'
        ordering = ['group', 'key']
        indexes = [
            models.Index(fields=['group']),
            models.Index(fields=['key']),
        ]
    
    def __str__(self):
        """返回配置的字符串表示"""
        return f"{self.group}.{self.key}"
    
    def get_typed_value(self):
        """根据类型返回正确的值"""
        if self.value_type == 'integer':
            return int(self.value)
        elif self.value_type == 'float':
            return float(self.value)
        elif self.value_type == 'boolean':
            return self.value.lower() in ('true', '1', 'yes', 'on')
        elif self.value_type == 'json':
            import json
            return json.loads(self.value)
        else:
            return self.value


class Notification(models.Model):
    """通知模型
    
    用户通知系统。
    """
    
    # 通知类型选择
    TYPE_CHOICES = [
        ('info', _('信息')),
        ('success', _('成功')),
        ('warning', _('警告')),
        ('error', _('错误')),
        ('system', _('系统')),
    ]
    
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
        verbose_name=_('通知ID')
    )
    
    # 接收者
    recipient = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='notifications',
        verbose_name=_('接收者')
    )
    
    # 通知内容
    title = models.CharField(
        _('标题'),
        max_length=200,
        help_text=_('通知的标题')
    )
    
    message = models.TextField(
        _('消息内容'),
        help_text=_('通知的详细内容')
    )
    
    notification_type = models.CharField(
        _('通知类型'),
        max_length=20,
        choices=TYPE_CHOICES,
        default='info',
        help_text=_('通知的类型')
    )
    
    # 关联对象（可选）
    content_type = models.ForeignKey(
        ContentType,
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        verbose_name=_('内容类型')
    )
    
    object_id = models.CharField(
        _('对象ID'),
        max_length=36,
        null=True,
        blank=True
    )
    
    content_object = GenericForeignKey('content_type', 'object_id')
    
    # 状态
    is_read = models.BooleanField(
        _('已读'),
        default=False,
        help_text=_('通知是否已被阅读')
    )
    
    # 链接
    action_url = models.URLField(
        _('操作链接'),
        blank=True,
        help_text=_('点击通知后跳转的链接')
    )
    
    # 时间字段
    created_at = models.DateTimeField(
        _('创建时间'),
        auto_now_add=True
    )
    
    read_at = models.DateTimeField(
        _('阅读时间'),
        null=True,
        blank=True
    )
    
    class Meta:
        verbose_name = _('通知')
        verbose_name_plural = _('通知')
        db_table = 'notification'
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['recipient', '-created_at']),
            models.Index(fields=['recipient', 'is_read']),
            models.Index(fields=['notification_type']),
        ]
    
    def __str__(self):
        """返回通知的字符串表示"""
        return f"{self.recipient.username}: {self.title}"
    
    def mark_as_read(self):
        """标记为已读"""
        if not self.is_read:
            from django.utils import timezone
            self.is_read = True
            self.read_at = timezone.now()
            self.save(update_fields=['is_read', 'read_at'])


class ActivityLog(models.Model):
    """活动日志模型
    
    记录用户的操作活动。
    """
    
    # 操作类型选择
    ACTION_CHOICES = [
        ('create', _('创建')),
        ('update', _('更新')),
        ('delete', _('删除')),
        ('view', _('查看')),
        ('share', _('分享')),
        ('comment', _('评论')),
        ('like', _('点赞')),
        ('login', _('登录')),
        ('logout', _('登出')),
    ]
    
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
        verbose_name=_('日志ID')
    )
    
    # 操作者
    user = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='activity_logs',
        verbose_name=_('操作者')
    )
    
    # 操作信息
    action = models.CharField(
        _('操作类型'),
        max_length=20,
        choices=ACTION_CHOICES,
        help_text=_('执行的操作类型')
    )
    
    description = models.TextField(
        _('操作描述'),
        help_text=_('操作的详细描述')
    )
    
    # 关联对象
    content_type = models.ForeignKey(
        ContentType,
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        verbose_name=_('内容类型')
    )
    
    object_id = models.CharField(
        _('对象ID'),
        max_length=36,
        null=True,
        blank=True
    )
    
    content_object = GenericForeignKey('content_type', 'object_id')
    
    # 请求信息
    ip_address = models.GenericIPAddressField(
        _('IP地址'),
        null=True,
        blank=True,
        help_text=_('操作者的IP地址')
    )
    
    user_agent = models.TextField(
        _('用户代理'),
        blank=True,
        help_text=_('操作者的浏览器信息')
    )
    
    # 额外数据
    extra_data = models.JSONField(
        _('额外数据'),
        null=True,
        blank=True,
        help_text=_('操作相关的额外数据')
    )
    
    # 时间字段
    created_at = models.DateTimeField(
        _('创建时间'),
        auto_now_add=True
    )
    
    class Meta:
        verbose_name = _('活动日志')
        verbose_name_plural = _('活动日志')
        db_table = 'activity_log'
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['user', '-created_at']),
            models.Index(fields=['action', '-created_at']),
            models.Index(fields=['content_type', 'object_id']),
            models.Index(fields=['ip_address']),
        ]
    
    def __str__(self):
        """返回日志的字符串表示"""
        user_name = self.user.username if self.user else '匿名用户'
        return f"{user_name} {self.get_action_display()}: {self.description}"


class FileUpload(models.Model):
    """文件上传模型
    
    管理系统中的文件上传。
    """
    
    # 文件类型选择
    FILE_TYPES = [
        ('image', _('图片')),
        ('document', _('文档')),
        ('archive', _('压缩包')),
        ('video', _('视频')),
        ('audio', _('音频')),
        ('other', _('其他')),
    ]
    
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
        verbose_name=_('文件ID')
    )
    
    # 文件信息
    file = models.FileField(
        _('文件'),
        upload_to='uploads/%Y/%m/',
        help_text=_('上传的文件')
    )
    
    original_name = models.CharField(
        _('原始文件名'),
        max_length=255,
        help_text=_('文件的原始名称')
    )
    
    file_type = models.CharField(
        _('文件类型'),
        max_length=20,
        choices=FILE_TYPES,
        default='other',
        help_text=_('文件的分类类型')
    )
    
    mime_type = models.CharField(
        _('MIME类型'),
        max_length=100,
        help_text=_('文件的MIME类型')
    )
    
    file_size = models.PositiveIntegerField(
        _('文件大小'),
        help_text=_('文件大小（字节）')
    )
    
    # 上传者
    uploaded_by = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='uploaded_files',
        verbose_name=_('上传者')
    )
    
    # 关联对象（可选）
    content_type = models.ForeignKey(
        ContentType,
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        verbose_name=_('内容类型')
    )
    
    object_id = models.CharField(
        _('对象ID'),
        max_length=36,
        null=True,
        blank=True
    )
    
    content_object = GenericForeignKey('content_type', 'object_id')
    
    # 访问控制
    is_public = models.BooleanField(
        _('公开访问'),
        default=False,
        help_text=_('文件是否可以公开访问')
    )
    
    # 统计信息
    download_count = models.PositiveIntegerField(
        _('下载次数'),
        default=0,
        help_text=_('文件被下载的次数')
    )
    
    # 时间字段
    created_at = models.DateTimeField(
        _('创建时间'),
        auto_now_add=True
    )
    
    class Meta:
        verbose_name = _('文件上传')
        verbose_name_plural = _('文件上传')
        db_table = 'file_upload'
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['uploaded_by', '-created_at']),
            models.Index(fields=['file_type']),
            models.Index(fields=['content_type', 'object_id']),
            models.Index(fields=['is_public']),
        ]
    
    def __str__(self):
        """返回文件的字符串表示"""
        return self.original_name
    
    @property
    def file_size_human(self):
        """返回人类可读的文件大小"""
        size = self.file_size
        for unit in ['B', 'KB', 'MB', 'GB']:
            if size < 1024:
                return f"{size:.1f} {unit}"
            size /= 1024
        return f"{size:.1f} TB"
    
    def get_file_extension(self):
        """获取文件扩展名"""
        import os
        return os.path.splitext(self.original_name)[1].lower()


class SystemStats(models.Model):
    """系统统计模型
    
    记录系统的统计数据。
    """
    
    # 统计类型选择
    STAT_TYPES = [
        ('daily', _('日统计')),
        ('weekly', _('周统计')),
        ('monthly', _('月统计')),
        ('yearly', _('年统计')),
    ]
    
    stat_type = models.CharField(
        _('统计类型'),
        max_length=20,
        choices=STAT_TYPES,
        help_text=_('统计数据的类型')
    )
    
    stat_date = models.DateField(
        _('统计日期'),
        help_text=_('统计数据对应的日期')
    )
    
    # 统计数据
    user_count = models.PositiveIntegerField(
        _('用户数量'),
        default=0,
        help_text=_('用户总数')
    )
    
    note_count = models.PositiveIntegerField(
        _('笔记数量'),
        default=0,
        help_text=_('笔记总数')
    )
    
    share_count = models.PositiveIntegerField(
        _('分享数量'),
        default=0,
        help_text=_('分享总数')
    )
    
    view_count = models.PositiveIntegerField(
        _('访问次数'),
        default=0,
        help_text=_('总访问次数')
    )
    
    active_users = models.PositiveIntegerField(
        _('活跃用户'),
        default=0,
        help_text=_('活跃用户数量')
    )
    
    # 额外统计数据
    extra_stats = models.JSONField(
        _('额外统计'),
        null=True,
        blank=True,
        help_text=_('其他统计数据')
    )
    
    # 时间字段
    created_at = models.DateTimeField(
        _('创建时间'),
        auto_now_add=True
    )
    
    updated_at = models.DateTimeField(
        _('更新时间'),
        auto_now=True
    )
    
    class Meta:
        verbose_name = _('系统统计')
        verbose_name_plural = _('系统统计')
        db_table = 'system_stats'
        unique_together = [['stat_type', 'stat_date']]
        ordering = ['-stat_date']
        indexes = [
            models.Index(fields=['stat_type', '-stat_date']),
            models.Index(fields=['-stat_date']),
        ]
    
    def __str__(self):
        """返回统计的字符串表示"""
        return f"{self.get_stat_type_display()} - {self.stat_date}"
